﻿using BITUI.Element;
using BITUI.Tile;
using SDL2;
using System;
using System.Collections.Generic;
using System.Text;

namespace BITUI.Element
{
    public class InputBox : IElement2D, IElementWithEvent
    {
        public InputBox(Tile.Bank bank, string deftext = "")
        {
            this.bank = bank;
            this.text = deftext;
            this.TileWidth = 10;
            this.TileHeight = 2;
            this.cursor = this.bank.GetTileByName("cursor");//cursor固定一像素宽，这样方便计算
            this.cursorpos = (uint)this.text.Length;

        }
        Tile.Bank bank;
        public string text;
        public byte colorReplace = 0;
        public byte colorReplaceSelect = 0x1B;

        RenderTile cursor;
        uint cursorpos = 0;
        uint cursorpos2 = 0;
        //背景 可选
        public IFillDraw backGround = null;
        public byte backGroundColorReplace = 0;
        public byte backGroundColorReplacePointOver = 0x35;
        public byte backGroundColorReplaceFocus = 0x39;
        public byte backGroundColorReplaceDisable = 0x10;

        //还要画 光标

        //裁剪边缘
        public byte clipborder = 1;
        //单行文本框，垂直居中，水平居左带滚动，只需要指定一个裁剪范围就有
        public IElement2DGroup Parent
        {
            get;
            private set;
        }


        public int TileXLocal { get; set; }
        public int TileYLocal { get; set; }

        public int TileX
        {
            get
            {
                if (this.Parent != null)
                    return this.Parent.TileX + this.TileXLocal;
                else
                    return this.TileXLocal;
            }
        }

        public int TileY
        {
            get
            {
                if (this.Parent != null)
                    return this.Parent.TileY + this.TileYLocal;
                else
                    return this.TileYLocal;
            }
        }
        public int TileWidth
        {
            get;
            set;
        }

        public int TileHeight
        {
            get;
            set;
        }

        public void SetParent(IElement2DGroup parent)
        {
            this.Parent = parent;
        }
        byte cursorFlashTimer = 0;
        public void OnDraw(IWindowRender render)
        {
            if (backGround != null)
            {
                byte state = 0;
                if (!Enable)
                    state = backGroundColorReplaceDisable;

                //如果有焦点，就显示 stateFocus
                //如果有焦点并按住， 就显示 statePress
                if (mouseOver)
                    state = backGroundColorReplacePointOver;


                if (focus)
                    state = backGroundColorReplaceFocus;

                if (state == 0)
                    state = backGroundColorReplace;

                backGround.FillDraw(render, this.TileX * 8, this.TileY * 8, this.TileWidth * 8, this.TileHeight * 8, state);
            }
            int x1 = this.TileX * 8 + clipborder;
            int y1 = this.TileY * 8 + clipborder;
            int x2 = (this.TileX + this.TileWidth) * 8 - clipborder;
            int y2 = (this.TileY + this.TileHeight) * 8 - clipborder;
            render.PushLimitTileRect(new LimitRect { xmin = x1, ymin = y1, xmax = x2, ymax = y2 });
            {
                //先这样吧，实际上因为输入滚动，所以 tx算法还得考虑光标
                int w = 0;
                int h = this.cursor.srcrect.h;

                int curx = 0;
                int curx2 = 0;
                for (var i = 0; i < this.text.Length; i++)
                {
                    var c = this.text[i];
                    var tile = this.bank.GetTileByName(c.ToString());
                    if (tile != null)
                    {
                        w += tile.srcrect.w;
                        h = Math.Max(h, tile.srcrect.h);
                    }
                    if (i < cursorpos)
                        curx += tile.srcrect.w;
                    if (i < cursorpos2)
                        curx2 += tile.srcrect.w;
                }
                var tx = this.TileX * 8 + this.clipborder;
                if (tx + curx2 > x2 - 1)
                {
                    this.xOffset = (curx2 + tx) - (x2 - 1);
                }
                else
                {
                    this.xOffset = 0;
                }
                var ty = this.TileY * 8 + (this.TileHeight * 8 - h) / 2;
                render.DrawTileByNames(this.bank, this.text, tx - this.xOffset, ty, this.colorReplace);

                if (this.focus)//活动时显示光标
                {
                    cursorFlashTimer++;
                    if (cursorFlashTimer > 60)
                        cursorFlashTimer = 0;
                    if (cursorpos == cursorpos2)
                    {
                        if (cursorFlashTimer < 30)//始终显示单光标
                        {
                            //int drawx = Math.Min(curx, curx2);

                            render.DrawTile(this.cursor, tx + curx2 - this.xOffset, ty, 0, 1, 1);
                        }
                    }
                    else
                    {
                        if (cursorFlashTimer < 30)//始终显示选中区
                        {
                            int width = Math.Abs(curx2 - curx);
                            int drawx = Math.Min(curx, curx2);
                            if (width == 0) width = 1;
                            render.DrawTile(this.cursor, tx + drawx - this.xOffset, ty, 0, width, 1);
                            if (cursorpos != cursorpos2)
                            {
                                var left = Math.Min(cursorpos, cursorpos2);
                                var right = Math.Max(cursorpos, cursorpos2);
                                var seltext = this.text.Substring((int)left, (int)(right - left));
                                render.DrawTileByNames(this.bank, seltext, tx + drawx - this.xOffset, ty, this.colorReplaceSelect);
                            }
                        }
                        else
                        {
                            render.DrawTile(this.cursor, tx + curx2 - this.xOffset, ty, 0, 1, 1);
                        }
                    }

                }
            }
            render.PopLimitTileRect();
        }


        bool mouseOver = false;
        bool focus = false;
        public bool Enable = true;
        bool mouseDown = false;

        public bool OnMouseDown(IWindowEvent win, byte button)
        {
            if (!this.mouseOver)
                return false;

            mouseDown = true;
            this.focus = true;
            var x1 = this.TileX * 8;
            var y1 = this.TileY * 8;
            var x2 = (this.TileX + this.TileWidth) * 8;
            var y2 = (this.TileY + this.TileHeight) * 8;

            {//改变光标位置
                int w = 0;
                var curX = lastPointX - x1 + xOffset;

                cursorpos2 = (uint)this.text.Length;
                for (var i = 0; i < this.text.Length; i++)
                {
                    var c = this.text[i];
                    var tile = this.bank.GetTileByName(c.ToString());
                    if (tile != null)
                    {
                        w += tile.srcrect.w;
                        if (w > curX)
                        {
                            cursorpos2 = (uint)i;
                            break;
                        }
                    }
                }
                this.cursorFlashTimer = 0;
            }
            if (!bShift)//按住shift只动一边
                cursorpos = cursorpos2;


            win.SetTextInput(lastPointX, y1, 0, 0);
            win.RegFocus(this);
            this.cursorFlashTimer = 0;
            return false;
        }
        int lastPointX = 0;
        int lastPointY = 0;
        int xOffset = 0;

        public bool OnMouseMove(IWindowEvent win, int x, int y)
        {
            var x1 = this.TileX * 8;
            var y1 = this.TileY * 8;
            var x2 = (this.TileX + this.TileWidth) * 8;
            var y2 = (this.TileY + this.TileHeight) * 8;

            lastPointX = x;
            lastPointY = y;
            if (x1 <= x && x <= x2 && y1 < y && y < y2)
            {
                if (!this.mouseOver)
                {
                    this.mouseOver = true;
                    win.RegPointOver(this);
                }
                if (this.focus && this.mouseDown)//按住了还在动
                {
                    {//改变光标位置
                        int w = 0;
                        var curX = lastPointX - x1 + xOffset;

                        cursorpos2 = (uint)this.text.Length;
                        for (var i = 0; i < this.text.Length; i++)
                        {
                            var c = this.text[i];
                            var tile = this.bank.GetTileByName(c.ToString());
                            if (tile != null)
                            {
                                w += tile.srcrect.w;
                                if (w > curX)
                                {
                                    cursorpos2 = (uint)i;
                                    break;
                                }
                            }
                        }
                        this.cursorFlashTimer = 0;
                    }
                }
                return false;
            }
            //到我这就没了
            return true;
        }

        public void OnMouseUp(IWindowEvent win, byte button)
        {
            mouseDown = false;
            //啥也不用干
        }


        public void OnMouseLeave(IWindowEvent win)
        {
            this.mouseOver = false;
        }
        public void OnLostFocus(IWindowEvent win)
        {
            this.focus = false;
            win.CloseTextInput();
        }


        public void OnInput(IWindowEvent win, string _text)
        {
            int leftlen = Math.Min((int)this.cursorpos, (int)this.cursorpos2);
            int rightstart = Math.Max((int)this.cursorpos, (int)this.cursorpos2);
            if (this.cursorpos2 != this.cursorpos)
            {
                this.cursorpos = (uint)leftlen;
                this.cursorpos2 = (uint)leftlen;
            }
            var lefttext = this.text.Substring(0, leftlen);
            var righttext = this.text.Substring(rightstart);
            this.text = lefttext + _text + righttext;
            this.cursorpos2 += (uint)_text.Length;
            this.cursorpos = this.cursorpos2;
            this.cursorFlashTimer = 0;
        }
        bool bCtrl = false;
        bool bShift = false;
        public void OnKey(IWindowEvent win, SDL.SDL_Scancode key, bool press)
        {
            if (key == SDL.SDL_Scancode.SDL_SCANCODE_LCTRL || key == SDL.SDL_Scancode.SDL_SCANCODE_RCTRL)
            {
                bCtrl = press;
            }
            if (key == SDL.SDL_Scancode.SDL_SCANCODE_LSHIFT || key == SDL.SDL_Scancode.SDL_SCANCODE_RSHIFT)
            {
                bShift = press;
            }
            if (press)
            {
                if (key == SDL.SDL_Scancode.SDL_SCANCODE_A && bCtrl)
                {
                    this.cursorpos = 0;
                    this.cursorpos2 = (uint)this.text.Length;
                    this.cursorFlashTimer = 0;
                }
                if (key == SDL.SDL_Scancode.SDL_SCANCODE_X && bCtrl)
                {
                    if (this.cursorpos != this.cursorpos2)
                    {
                        int leftlen = Math.Min((int)this.cursorpos, (int)this.cursorpos2);
                        int rightstart = Math.Max((int)this.cursorpos, (int)this.cursorpos2);
                        var cliptext = this.text.Substring(leftlen, rightstart - leftlen);

                        SDL.SDL_SetClipboardText(cliptext);

                        var lefttext = this.text.Substring(0, leftlen);
                        var righttext = this.text.Substring(rightstart);
                        this.text = lefttext + righttext;
                        this.cursorpos2 = (uint)leftlen;
                        this.cursorpos = this.cursorpos2;
                        this.cursorFlashTimer = 0;

                    }
                }
                if (key == SDL.SDL_Scancode.SDL_SCANCODE_C && bCtrl)
                {
                    if (this.cursorpos != this.cursorpos2)
                    {
                        int leftlen = Math.Min((int)this.cursorpos, (int)this.cursorpos2);
                        int rightstart = Math.Max((int)this.cursorpos, (int)this.cursorpos2);
                        var cliptext = this.text.Substring(leftlen, rightstart - leftlen);

                        SDL.SDL_SetClipboardText(cliptext);
                        this.cursorFlashTimer = 0;

                    }
                }
                if (key == SDL.SDL_Scancode.SDL_SCANCODE_V && bCtrl)
                {
                    //移除那些乱七八糟的字符
                    var text = SDL.SDL_GetClipboardText();
                    text = text.Replace("\r", "");
                    text = text.Replace("\n", "");
                    text = text.Replace("\t", "");
                    this.OnInput(win, text);

                }
                if (key == SDL.SDL_Scancode.SDL_SCANCODE_LEFT)
                {
                    if (this.cursorpos2 > 0)
                    {
                        this.cursorpos2--;
                        if (!bShift)//shift按下只移动一边光标
                            this.cursorpos = this.cursorpos2;

                        cursorFlashTimer = 0;
                    }
                }
                if (key == SDL.SDL_Scancode.SDL_SCANCODE_RIGHT)
                {
                    if (this.cursorpos2 < this.text.Length)
                    {
                        this.cursorpos2++;
                        if (!bShift)//shift按下只移动一边光标
                            this.cursorpos = this.cursorpos2;
                        cursorFlashTimer = 0;
                    }
                }
                if (key == SDL.SDL_Scancode.SDL_SCANCODE_DELETE)
                {
                    if (this.cursorpos2 < this.text.Length)
                    {
                        if (this.cursorpos2 == this.cursorpos) //单删
                        {
                            var lefttext = this.text.Substring(0, (int)this.cursorpos2);
                            var righttext = this.text.Substring((int)this.cursorpos2 + 1);
                            this.text = lefttext + righttext;
                        }
                        else //多选删
                        {
                            int leftlen = Math.Min((int)this.cursorpos, (int)this.cursorpos2);
                            int rightstart = Math.Max((int)this.cursorpos, (int)this.cursorpos2);
                            var lefttext = this.text.Substring(0, leftlen);
                            var righttext = this.text.Substring(rightstart);
                            this.text = lefttext + righttext;
                            this.cursorpos2 = (uint)leftlen;
                        }
                        this.cursorpos = this.cursorpos2;

                        cursorFlashTimer = 0;
                    }
                }
                if (key == SDL.SDL_Scancode.SDL_SCANCODE_BACKSPACE)
                {
                    if (this.cursorpos2 > 0)
                    {
                        if (this.cursorpos2 == this.cursorpos) //单删
                        {
                            this.cursorpos2--;
                            var lefttext = this.text.Substring(0, (int)this.cursorpos2);
                            var righttext = this.text.Substring((int)this.cursorpos2 + 1);
                            this.text = lefttext + righttext;
                        }
                        else //多选删，只删除选中，光标不左移
                        {
                            int leftlen = Math.Min((int)this.cursorpos, (int)this.cursorpos2);
                            int rightstart = Math.Max((int)this.cursorpos, (int)this.cursorpos2);
                            var lefttext = this.text.Substring(0, leftlen);
                            var righttext = this.text.Substring(rightstart);
                            this.text = lefttext + righttext;
                            this.cursorpos2 = (uint)leftlen;
                        }
                        this.cursorpos = this.cursorpos2;
                        cursorFlashTimer = 0;
                    }
                }
            }
        }
        public bool OnMouseWheel(IWindowEvent win, uint dir, int x, int y)
        {
            return true;
        }

    }
}
